package com.jack.lib.core.utils;

import android.accounts.NetworkErrorException;
import android.annotation.SuppressLint;
import android.os.Message;

import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import android.util.Log;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;

/**
 * Created by chong on 2017/10/26.
 */

public class NetworkUtils {

    @IntDef({GET,POST})
    public @interface Method{}

    public static final int GET = 1;
    public static final int POST = 2;

    private static final int ERROR = 10;
    private static final int NEXT = 11;

    public static int sConnectTimeout = 5000;

    public static int sReadTimeout = 3000;

    private Map<String,String> mMap;
    private String mPath;
    private int mMethod;



    @SuppressLint("HandlerLeak")
    private android.os.Handler mHandler = new android.os.Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case ERROR:
                    if (mOnRequestNetworkListenet != null)mOnRequestNetworkListenet.onError((Exception) msg.obj);
                    if (mOnRequestNetworkListenet != null)mOnRequestNetworkListenet.onComplete();
                    break;
                case NEXT:
                    try {
                        if (mOnRequestNetworkListenet != null)mOnRequestNetworkListenet.onNext((String) msg.obj);
                        if (mOnRequestFinishListener != null)mOnRequestFinishListener.onNext((String) msg.obj);
                        if (mOnRequestNetworkListenet != null)mOnRequestNetworkListenet.onComplete();
                    }catch (Exception e){
                        if (mOnRequestNetworkListenet != null)mOnRequestNetworkListenet.onError(e);
                        if (mOnRequestNetworkListenet != null)mOnRequestNetworkListenet.onComplete();
                    }
                    break;
            }
        }
    };


    private OnRequestNetworkListenet mOnRequestNetworkListenet;

    private OnRequestFinishListener mOnRequestFinishListener;

    public interface OnRequestNetworkListenet<T>{

        void onComplete();

        void onError(Exception e);

        void onNext(T json);
    }

    public interface OnRequestFinishListener<T>{
        void onNext(String json);
    }


    public static void initParameter(int connectTimeout, int readTimeout){
        sConnectTimeout = connectTimeout;
        sReadTimeout = readTimeout;
    }



    public void setOnRequestListenet(@NonNull OnRequestNetworkListenet onRequestNetworkListenet){
        mOnRequestNetworkListenet = onRequestNetworkListenet;
    }

    public void setOnRequestListenet(@NonNull OnRequestFinishListener onRequestFinishListener){
        mOnRequestFinishListener = onRequestFinishListener;
    }

    private void checkMethod(){
        if (mMethod == GET){
            mPath += "?";
            for (Map.Entry<String, String> stringStringEntry : mMap.entrySet()) {
                mPath += stringStringEntry.getKey() + "=" + stringStringEntry.getValue() + "&";
            }
        }
    }

    private StringBuffer getParameterString(){
        StringBuffer mStringBuffer = new StringBuffer();
        for (Map.Entry<String, String> stringStringEntry : mMap.entrySet()) {
            mStringBuffer.append(stringStringEntry.getKey() + "=" + stringStringEntry.getValue() + "&");
        }
        return mStringBuffer;
    }

    public void requestNetwork(@NonNull String path, @NonNull Map<String,String> parameter){
        requestNetwork(path,parameter,GET);
    }

    public void requestNetwork(@NonNull String path, @NonNull Map<String,String> parameter, @Method int method) {
        mMap = parameter;
        mPath = path;
        mMethod = method;
        run();
    }


    public void run() {
        new Thread(mRunnable).start();
    }

    private Runnable mRunnable = new Runnable() {
        @Override
        public void run() {
            checkMethod();
            try {
                URL url = new URL(mPath);
                HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
                httpURLConnection.setConnectTimeout(sConnectTimeout);
                httpURLConnection.setReadTimeout(sReadTimeout);
                httpURLConnection.setRequestMethod(mMethod == GET ? "GET" : "POST");

                if (mMethod == POST){
                    StringBuffer parameterString = getParameterString();
//                    httpURLConnection.setRequestProperty("Content-Type", "multipart/form-data");
                    httpURLConnection.setRequestProperty("Content-Length", String.valueOf(parameterString.toString().getBytes().length));
                    OutputStream outputStream = httpURLConnection.getOutputStream();
                    outputStream.write(parameterString.toString().getBytes());
                }

                int responseCode = httpURLConnection.getResponseCode();
                if (responseCode != 200) {
                    Message message = mHandler.obtainMessage();
                    message.obj = new NetworkErrorException(getJsonString(httpURLConnection.getErrorStream()));
                    message.what = ERROR;
                    mHandler.sendMessage(message);
                    return;
                }

                String json = getJsonString(httpURLConnection.getInputStream());

                Message message = mHandler.obtainMessage();
                message.obj = json;
                message.what = NEXT;
                mHandler.sendMessage(message);

            }catch (Exception e) {
                Log.e("TAG",e.toString());

                Message message = mHandler.obtainMessage();
                message.obj = e;
                message.what = ERROR;
                mHandler.sendMessage(message);
            }
        }
    };


    private String getJsonString(InputStream inputStream) throws IOException {
        ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();
        int i;
        while ((i = inputStream.read()) != -1){
            arrayOutputStream.write(i);
        }
        return arrayOutputStream.toString();
    }

}
